home *** CD-ROM | disk | FTP | other *** search
- /* Machine or compiler-dependent portions of kernel */
- #include "global.h"
- #include "proc.h"
-
- extern char Intstk[];
- extern unsigned short dbase,cbase;
-
- #if (sizeof(int (*)()) == 4)
- #define LARGECODE 1
- #endif
-
- /* Segment number of pointer */
- #define FP_SEG(x) (sizeof(x) == 4 ? ((long)(x) >> 16) : dbase)
- /* Offset of pointer */
- #define FP_OFF(x) ((unsigned short)((long)(x) & 0xffff))
-
-
- /* Template for contents of jmp_buf in Aztec C */
- struct env {
- unsigned short sp; /* Stack pointer */
- unsigned short bp; /* Context pointer */
- unsigned short si; /* Register variables */
- unsigned short di;
- unsigned short ip; /* Program counter */
- unsigned short cs; /* Code segment -- only in large code model */
- };
-
- kinit()
- {
- /* Initialize interrupt stack for high-water-mark checking */
- memset(Intstk,STACKPAT,512);
-
- /* Init location 0 with pattern to detect null pointer derefs */
- *(unsigned short *)NULL = NULLPAT;
- }
- /* Print process table info
- * Since things can change while ps is running, the ready proceses are
- * displayed last. This is because an interrupt can make a process ready,
- * but a ready process won't spontaneously become unready. Therefore a
- * process that changes during ps may show up twice, but this is better
- * than not having it showing up at all.
- */
- int
- ps()
- {
- register struct proc *pp;
- register struct env *ep;
- int i;
-
- printf("Code %x Data %x Stack %x max intstk %u\n",cbase,dbase,getss(),chkintstk());
-
- printf("PID SP stksize maxstk event flags name\n");
-
- for(pp = Susptab;pp != NULLPROC;pp = pp->next){
- ep = (struct env *)&pp->env;
- printf("%-10lx%-10x%-10u%-10u%-10lx%c%c%c %s\n",
- ptol(pp),
- ep->sp,
- pp->stksize,
- stkutil(pp),
- ptol(pp->event),
- pp->i_state ? 'I' : ' ',
- (pp->state & WAITING) ? 'W' : ' ',
- (pp->state & SUSPEND) ? 'S' : ' ',
- pp->name);
- }
- for(i=0;i<PHASH;i++){
- for(pp = Waittab[i];pp != NULLPROC;pp = pp->next){
- ep = (struct env *)&pp->env;
- printf("%-10lx%-10x%-10u%-10u%-10lx%c%c%c %s\n",
- ptol(pp),ep->sp,pp->stksize,stkutil(pp),
- ptol(pp->event),
- pp->i_state ? 'I' : ' ',
- (pp->state & WAITING) ? 'W' : ' ',
- (pp->state & SUSPEND) ? 'S' : ' ',
- pp->name);
- }
- }
- for(pp = Rdytab;pp != NULLPROC;pp = pp->next){
- ep = (struct env *)&pp->env;
- printf("%-10lx%-10x%-10u%-10u %c%c%c %s\n",
- ptol(pp),ep->sp,pp->stksize,stkutil(pp),
- pp->i_state ? 'I' : ' ',
- (pp->state & WAITING) ? 'W' : ' ',
- (pp->state & SUSPEND) ? 'S' : ' ',
- pp->name);
- }
- if(Curproc != NULLPROC){
- ep = (struct env *)&Curproc->env;
- printf("%-10lx%-10x%-10u%-10u %c %s\n",
- ptol(Curproc),ep->sp,Curproc->stksize,
- stkutil(Curproc),
- Curproc->i_state ? 'I' : ' ',
- Curproc->name);
- }
- return 0;
- }
- int
- stkutil(pp)
- struct proc *pp;
- {
- unsigned i;
- register char *sp;
-
- i = pp->stksize;
- for(sp = pp->stack;*sp == STACKPAT && sp < pp->stack + pp->stksize;sp++)
- i--;
- return i;
- }
- /* Return number of used bytes in interrupt stack. Note hardwired value
- * of 512; this is also found in the various .asm files
- */
- chkintstk()
- {
- register int i;
- register char *cp;
-
- i = 512;
- for(cp = Intstk; *cp == STACKPAT && cp < &Intstk[512]; cp++)
- i--;
- return i;
- }
-
- /* Verify that stack pointer for specified process is within legal limits;
- * also check that no one has dereferenced a null pointer
- */
- void
- chkstk(pp)
- struct proc *pp;
- {
- register struct env *ep;
- unsigned short sbase,stop;
-
- if(pp == NULLPROC)
- return;
- ep = (struct env *) &pp->env;
- sbase = (unsigned short) pp->stack;
- stop = sbase + pp->stksize;
- if(ep->sp < sbase || ep->sp >= stop){
- printf("Stack violation, process %s\n",pp->name);
- printf("SP = %x, legal stack range [%x,%x)\n",ep->sp,sbase,stop);
- killproc(pp);
- }
- if(*(unsigned short *)NULL != NULLPAT){
- printf("WARNING: Location 0 smashed, process %s\n",pp->name);
- *(unsigned short *)NULL = NULLPAT;
- }
- }
- /* Machine-dependent initialization of a task */
- psetup(pp,iarg,parg,pc)
- struct proc *pp; /* Pointer to task structure */
- int iarg; /* Integer argument */
- char *parg; /* Generic pointer argument */
- void (*pc)(); /* Initial execution address */
- {
- register int *stktop;
- register struct env *ep;
-
- /* Set up stack to make it appear as if the user's function was called
- * by killself() with the specified arguments. When the user returns,
- * killself() automatically cleans up.
- *
- * First, push args on stack in reverse order, simulating what C
- * does just before it calls a function.
- */
- stktop = (int *)(pp->stack + pp->stksize);
- *--stktop = (int)parg;
- *--stktop = iarg;
-
- /* Now push the entry address of killself(), simulating the call to
- * the user function.
- */
- #ifdef LARGECODE
- *--stktop = FP_SEG(&killself);
- #endif
- *--stktop = FP_OFF(&killself);
-
- /* Set up environment in jmp buf */
- ep = (struct env *)&pp->env;
- ep->sp = FP_OFF(stktop);
- ep->cs = FP_SEG(pc); /* Doesn't hurt in small model */
- ep->ip = FP_OFF(pc);
- /* Task initially runs with interrupts on */
- pp->i_state = 1;
- }
-
-